package allod.som

import allod.som.Lattice.NeuronLocation
import allod.som.Lattice.Pattern
import input.InputSource
import java.awt.Color
import swing.Label
import upgma.{IdentityCluster, Cluster}

/**
 * Created by IntelliJ IDEA.
 * User: allod
 * Date: 13 лют 2010
 * Time: 17:45:24
 */
class LabeledLattice[T] private(lattice: Lattice) {
  val columns = lattice.columns

  val rows = lattice.rows

  private lazy val labels = new Array[Array[T]](columns, rows)

  def peer = lattice

  def labelAt(index: NeuronLocation): T = labels(index._1)(index._2)

  def labelAt(row: Int, column: Int): T = labels(row)(column)

  private def markNeuronAt(index: NeuronLocation, label: T) {
    labels(index._1)(index._2) = label
  }
}

object LabeledLattice {
  implicit def labeledLatticeToLattice(labeledLattice: LabeledLattice[_]): Lattice = labeledLattice.peer

  def clusterLabelCreator(clusters: Seq[Cluster])(cluster: Cluster): Label = {
    val color = clusterColorCreator(clusters)(cluster)
    new Label() {
      text = cluster.name
      background = color
      opaque = true
    }
  }

  def clusterColorCreator(clusters: Seq[Cluster])(cluster: Cluster): Color = {
    val delta: Float = 1.0f / (clusters.size)
    var colorHeight = delta / 2 + clusters.findIndexOf(_ == cluster) * delta
    Color.getHSBColor(colorHeight, 1, 1)
  }

  class Marker[T](val lattice: Lattice) {
    def createLabeledLattice(clusters: Seq[Cluster], createLabel: Cluster => T): LabeledLattice[T] = {
      val labeledLattice = new LabeledLattice[T](lattice)
      for (cluster <- clusters) {
        for (IdentityCluster(neuron) <- cluster.getIdentityClusters)
          labeledLattice.markNeuronAt(neuron, createLabel(cluster))
      }
      labeledLattice
    }

    def createLabeledLattice(patterns: InputSource, createLabel: Pattern => T): LabeledLattice[T] = {
      val labeledLattice = new LabeledLattice[T](lattice)
      for (layer <- 0 until labeledLattice.columns; neuron <- 0 until labeledLattice.rows) {
        val pattern = lattice.closestPattern((layer, neuron), patterns)
        labeledLattice.markNeuronAt((layer, neuron), createLabel(pattern))
      }
      labeledLattice
    }
  }
}